package zero.tech.games.pdk.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import zero.tech.core.data.KeyVal;
import zero.tech.games.pdk.data.PdkConfig;
import zero.tech.games.pdk.data.entity.Card;
import zero.tech.games.pdk.data.entity.DispatchData;
import zero.tech.games.pdk.data.entity.PdkOut;
import zero.tech.wsnet.controller.LogicController;

public class CardUtil {
	public static List<Card> deck(){
		List<Card> list=new ArrayList<Card>();
		for(int i=1;i<=4;i++) {
			for(int j=3;j<=15;j++) {
				Card card=new Card(i,j);
				list.add(card);
			}
		}
		list.add(new Card(5,16));
		list.add(new Card(6,17));
		return list;
	}
	
	public static List<Card> deckWithoutJoker(){
		List<Card> list=new ArrayList<Card>();
		for(int i=1;i<=4;i++) {
			for(int j=3;j<=15;j++) {
				Card card=new Card(i,j);
				list.add(card);
			}
		}
		return list;
	}
	
	public static List<Card> pdk16mode(){
		List<Card> list=new ArrayList<Card>();
		for(int i=1;i<=4;i++) {
			for(int j=3;j<=13;j++) {
				Card card=new Card(i,j);
				list.add(card);
			}
		}
		list.add(new Card(1,14));
		list.add(new Card(2,14));
		list.add(new Card(3,14));
		list.add(new Card(1,15));
		return list;
	}
	
	
	public static List<Card> pdk16modeChou4(){
		List<Card> list=new ArrayList<>();
		List<Card> tmp=deckWithoutJoker();
		Collections.shuffle(tmp);
		list.addAll(tmp.subList(0, tmp.size()-4));
		return list;
	}
	
	public static List<Card> pdk15mode(){
		List<Card> list=new ArrayList<Card>();
		for(int i=1;i<=4;i++) {
			for(int j=3;j<=12;j++) {
				Card card=new Card(i*1,j);
				list.add(card);
			}
		}
		list.add(new Card(1,13));
		list.add(new Card(2,13));
		list.add(new Card(3,13));
		list.add(new Card(1,14));
		list.add(new Card(1,15));
		return list;
	}

	public static Map<Integer,Integer> numMap(List<Card> list) {
		Map<Integer,Integer> numMap=new HashMap<Integer, Integer>();
		for(Card card:list) {
			int num=card.getCardNum();
			if(!numMap.containsKey(num)) {
				numMap.put(num, 1);
			}else {
				int old=numMap.get(num);
				numMap.put(num,old+1);
			}
		}
		return numMap;
	}
	
	
	public static List<KeyVal<Integer, Integer>> keyVals(List<Card> list) {
		Map<Integer,Integer> numMap=numMap(list);
		List<KeyVal<Integer, Integer>> result=new ArrayList<>();
		for(Entry<Integer,Integer> entry:numMap.entrySet()) {
			result.add(new KeyVal<Integer, Integer>(entry.getKey(), entry.getValue()));
		}
		return result;
	}
	

	public static PdkOut autoFollow(List<Card> hands, PdkOut po, PdkConfig pdkConfig) {
		int cardstype=po.getCardstype();
		int length=po.getOuts().size();
		int max=po.getMax();
		PdkOut find=null;
		if(cardstype==CardsType.DAN) {//单张
			find=lookFollowDan(hands,cardstype,max,length);
		}else if(cardstype==CardsType.DUI) {//对子
			find=lookFollowDui(hands,cardstype,max,length);
		}else if(cardstype==CardsType.SHUN) {//顺子
			find=lookFollowShun(hands,cardstype,max,length);
		}else if(cardstype==CardsType.LIAN_DUI) {//连队
			find=lookFollowLianDui(hands,cardstype,max,length);
		}else if(cardstype==CardsType.FEI_JI) {//飞机
			int count=length/5;
			if(hands.size()>=count*3) {
				find=lookFollowFeiji(hands,cardstype,max,length);
			}
		}else if(cardstype==CardsType.ZHA_DAN) {//炸弹
			find=lookFollowZhadan(hands,cardstype,max,length,pdkConfig);
		}else if(cardstype==CardsType.SAN_DAI_ER) {//三带二
			find=lookFollowSandaier(hands,cardstype,max,length);
			if(find==null) {
				if(hands.size()==4) {
					find=lookFollowSandaidan(hands, cardstype, max, length);
				}
				if(hands.size()==3) {
					find=lookFollowSan(hands,cardstype,max,length);
				}
			}
		}else if(cardstype==CardsType.SI_DAI_ER) {//四带二
			if(pdkConfig.getSidaier()==1) {
				find=lookFollowSidaier(hands,cardstype,max,length);
				if(find==null&&pdkConfig.getSanazhadan()==1) {
					//三a炸弹
					find=lookFollowSidaierBySana(hands,cardstype,max,length);
				}
				if(find==null&&hands.size()==5) {
					find=lookFollowSidaidan(hands, cardstype, max, length);
				}
			}
		}else if(cardstype==CardsType.SI_DAI_SAN) {//四带三
			if(pdkConfig.getSidaisan()==1) {
				find=lookFollowSidaisan(hands,cardstype,max,length);
				if(hands.size()==6) {
					if(find==null&&pdkConfig.getSanazhadan()==1) {
						//三a炸弹
						find=lookFollowSidaisanBySana(hands,cardstype,max,length);
					}
					if(find==null) {
						find=lookFollowSidaier(hands,cardstype,max,length);
					}
					if(find==null&&hands.size()==5) {
						find=lookFollowSidaidan(hands, cardstype, max, length);
					}
				}
			}
		}
		if(find==null) {
			find=lookFollowZhadan(hands, cardstype, max, length,pdkConfig);
		}
		return find;
	}


	private static PdkOut lookFollowSidaierBySana(List<Card> hands, int cardstype, int max, int length) {
		List<KeyVal<Integer, Integer>> tmp=keyVals(hands);
		KeyVal<Integer,Integer> kv=null;
		for(KeyVal<Integer, Integer> find:tmp) {
			if(find.getV()>=3&&find.getK()==14) {
				kv=find;
				break;
			}
		}
		if(kv!=null) {
			int cardnum=kv.getK();
			if(cardnum>max) {
				//找到了
				List<Card> tt=new ArrayList<>();
				tt.addAll(hands);
				List<Card> out=select(tt,cardnum,3);
				//剩下的找三张
				List<Card> left=selectLeftForDan(tt,2);
				out.addAll(left);
				return new PdkOut(cardstype, cardnum, out);
			}
		}
		return null;
	}

	private static PdkOut lookFollowSidaisanBySana(List<Card> hands, int cardstype, int max, int length) {
		List<KeyVal<Integer, Integer>> tmp=keyVals(hands);
		KeyVal<Integer,Integer> kv=null;
		for(KeyVal<Integer, Integer> find:tmp) {
			if(find.getV()>=3&&find.getK()==14) {
				kv=find;
				break;
			}
		}
		if(kv!=null) {
			int cardnum=kv.getK();
			if(cardnum>max) {
				//找到了
				List<Card> tt=new ArrayList<>();
				tt.addAll(hands);
				List<Card> out=select(tt,cardnum,3);
				//剩下的找三张
				List<Card> left=selectLeftForDan(tt,3);
				out.addAll(left);
				return new PdkOut(cardstype, cardnum, out);
			}
		}
		return null;
	}

	private static PdkOut lookFollowFeiji(List<Card> hands, int cardstype, int max, int length) {
		int count=length/5;
		List<KeyVal<Integer, Integer>> tmp=keyVals(hands);
		List<KeyVal<Integer,Integer>>list=new ArrayList<>();
		for(KeyVal<Integer, Integer> find:tmp) {
			if(find.getK()>=3&&find.getK()<=14) {
				if(find.getV()>=3) {
					list.add(find);
				}
			}
		}
		if(list.size()>=2) {
			//找所有可能的顺子
			List<Integer> nums=new ArrayList<>();
			Map<Integer,Integer> mm=new HashMap<>();
			for(KeyVal<Integer,Integer> kv:list) {
				nums.add(kv.getK());
				mm.put(kv.getK(), kv.getV());
			}
			boolean find=false;
			int find_max=0;
			List<List<Integer>> allShunzi=getAllShunzi(nums);
			List<Integer> findshunzi=new ArrayList<>();
			//检查这些顺子哪些合法
			for(List<Integer> shunzi:allShunzi) {
				int size=shunzi.size();
				if(size>=count) {
					Collections.sort(shunzi,new Comparator<Integer>() {
						
						@Override
						public int compare(Integer o1, Integer o2) {
							return o2-o1;
						}
					});
					find_max=shunzi.get(0);
					if(find_max>max) {
						find=true;
						findshunzi.addAll(shunzi);
						break;
					}
				}
			}
			if(find) {
				List<Card> cards=new ArrayList<>();
				List<Card> tt=new ArrayList<>();
				tt.addAll(hands);
				for(Integer cardnum:findshunzi) {
					int findcount=mm.get(cardnum);
					List<Card> out=select(tt,cardnum,findcount);
					cards.addAll(out);
				}
				int leftcount=length-cards.size();
				List<Card> left=selectLeftForDan(tt,leftcount);
				cards.addAll(left);
				return new PdkOut(CardsType.FEI_JI,find_max , cards);
			}
		}
		
		return null;
	}


	private static PdkOut lookFollowSidaisan(List<Card> hands, int cardstype, int max, int length) {
		List<KeyVal<Integer, Integer>> tmp=keyVals(hands);
		List<KeyVal<Integer,Integer>>list=new ArrayList<>();
		for(KeyVal<Integer, Integer> find:tmp) {
			if(find.getV()>=4) {
				list.add(find);
			}
		}
		Collections.sort(list,new Comparator<KeyVal<Integer,Integer>>() {

			@Override
			public int compare(KeyVal<Integer, Integer> o1, KeyVal<Integer, Integer> o2) {
				int a= o1.getV()-o2.getV();
				if(a==0) {
					a=o1.getK()-o2.getK();
				}
				return a;
			}
		});
		for(KeyVal<Integer, Integer> find:list) {
			int cardnum=find.getK();
			if(cardnum>max) {
				//找到了
				List<Card> tt=new ArrayList<>();
				tt.addAll(hands);
				List<Card> out=select(tt,cardnum,4);
				//剩下的找一张
				List<Card> left=selectLeftForDan(tt,3);
				out.addAll(left);
				return new PdkOut(cardstype, cardnum, out);
			}
		}
		return null;
	}

	private static PdkOut lookFollowSidaier(List<Card> hands, int cardstype, int max, int length) {
		List<KeyVal<Integer, Integer>> tmp=keyVals(hands);
		List<KeyVal<Integer,Integer>>list=new ArrayList<>();
		for(KeyVal<Integer, Integer> find:tmp) {
			if(find.getV()>=4) {
				list.add(find);
			}
		}
		Collections.sort(list,new Comparator<KeyVal<Integer,Integer>>() {

			@Override
			public int compare(KeyVal<Integer, Integer> o1, KeyVal<Integer, Integer> o2) {
				int a= o1.getV()-o2.getV();
				if(a==0) {
					a=o1.getK()-o2.getK();
				}
				return a;
			}
		});
		for(KeyVal<Integer, Integer> find:list) {
			int cardnum=find.getK();
			if(cardnum>max) {
				//找到了
				List<Card> tt=new ArrayList<>();
				tt.addAll(hands);
				List<Card> out=select(tt,cardnum,4);
				//剩下的找一张
				List<Card> left=selectLeftForDan(tt,2);
				out.addAll(left);
				return new PdkOut(cardstype, cardnum, out);
			}
		}
		return null;
	}

	private static PdkOut lookFollowSidaidan(List<Card> hands, int cardstype, int max, int length) {
		List<KeyVal<Integer, Integer>> tmp=keyVals(hands);
		List<KeyVal<Integer,Integer>>list=new ArrayList<>();
		for(KeyVal<Integer, Integer> find:tmp) {
			if(find.getV()>=4) {
				list.add(find);
			}
		}
		Collections.sort(list,new Comparator<KeyVal<Integer,Integer>>() {

			@Override
			public int compare(KeyVal<Integer, Integer> o1, KeyVal<Integer, Integer> o2) {
				int a= o1.getV()-o2.getV();
				if(a==0) {
					a=o1.getK()-o2.getK();
				}
				return a;
			}
		});
		for(KeyVal<Integer, Integer> find:list) {
			int cardnum=find.getK();
			if(cardnum>max) {
				//找到了
				List<Card> tt=new ArrayList<>();
				tt.addAll(hands);
				List<Card> out=select(tt,cardnum,4);
				//剩下的找一张
				List<Card> left=selectLeftForDan(tt,1);
				out.addAll(left);
				return new PdkOut(cardstype, cardnum, out);
			}
		}
		return null;
	}

	private static PdkOut lookFollowSandaidan(List<Card> hands, int cardstype, int max, int length) {
		List<KeyVal<Integer, Integer>> tmp=keyVals(hands);
		List<KeyVal<Integer,Integer>>list=new ArrayList<>();
		for(KeyVal<Integer, Integer> find:tmp) {
			if(find.getV()>=3) {
				list.add(find);
			}
		}
		Collections.sort(list,new Comparator<KeyVal<Integer,Integer>>() {

			@Override
			public int compare(KeyVal<Integer, Integer> o1, KeyVal<Integer, Integer> o2) {
				int a= o1.getV()-o2.getV();
				if(a==0) {
					a=o1.getK()-o2.getK();
				}
				return a;
			}
		});
		for(KeyVal<Integer, Integer> find:list) {
			int cardnum=find.getK();
			if(cardnum>max) {
				//找到了
				List<Card> tt=new ArrayList<>();
				tt.addAll(hands);
				List<Card> out=select(tt,cardnum,3);
				//剩下的找一张
				List<Card> left=selectLeftForDan(tt,1);
				out.addAll(left);
				return new PdkOut(cardstype, cardnum, out);
			}
		}
		return null;
	}

	private static PdkOut lookFollowSandaier(List<Card> hands, int cardstype, int max, int length) {
		List<KeyVal<Integer, Integer>> tmp=keyVals(hands);
		List<KeyVal<Integer,Integer>>list=new ArrayList<>();
		for(KeyVal<Integer, Integer> find:tmp) {
			if(find.getV()>=3) {
				list.add(find);
			}
		}
		Collections.sort(list,new Comparator<KeyVal<Integer,Integer>>() {

			@Override
			public int compare(KeyVal<Integer, Integer> o1, KeyVal<Integer, Integer> o2) {
				int a= o1.getV()-o2.getV();
				if(a==0) {
					a=o1.getK()-o2.getK();
				}
				return a;
			}
		});
		for(KeyVal<Integer, Integer> find:list) {
			int cardnum=find.getK();
			if(cardnum>max) {
				//找到了
				List<Card> tt=new ArrayList<>();
				tt.addAll(hands);
				List<Card> out=select(tt,cardnum,3);
				//剩下的找两张
				List<Card> left=selectLeftForDan(tt,2);
				out.addAll(left);
				return new PdkOut(cardstype, cardnum, out);
			}
		}
		return null;
	}

	private static List<Card> selectLeftForDan(List<Card> tt, int size) {
		List<Card> result=new ArrayList<>();
		List<KeyVal<Integer, Integer>> tmp=keyVals(tt);
		List<KeyVal<Integer,Integer>>list=new ArrayList<>();
		for(KeyVal<Integer, Integer> find:tmp) {
			if(find.getV()>=1) {
				list.add(find);
			}
		}
		Collections.sort(list,new Comparator<KeyVal<Integer,Integer>>() {

			@Override
			public int compare(KeyVal<Integer, Integer> o1, KeyVal<Integer, Integer> o2) {
				int a= o1.getV()-o2.getV();
				if(a==0) {
					a=o1.getK()-o2.getK();
				}
				return a;
			}
		});
		for(KeyVal<Integer, Integer> keyVal:list) {
			int cardnum=keyVal.getK();
			int count=keyVal.getV();
			if(size<count) {
				result.addAll(select(tt, cardnum, size));
				break;
			}else {
				result.addAll(select(tt, cardnum, count));
				size-=count;
			}
		}
		return result;
	}

	private static PdkOut lookFollowZhadan(List<Card> hands, int cardstype, int max, int length, PdkConfig pdkConfig) {
		List<KeyVal<Integer, Integer>> tmp=keyVals(hands);
		List<KeyVal<Integer,Integer>>list=new ArrayList<>();
		for(KeyVal<Integer, Integer> find:tmp) {
			if(pdkConfig.getSanazhadan()==1) {
				if(find.getV()==3&&find.getK()==14) {
					list.add(find);
				}
			}
			if(find.getV()>=4) {
				list.add(find);
			}
		}
		Collections.sort(list,new Comparator<KeyVal<Integer,Integer>>() {

			@Override
			public int compare(KeyVal<Integer, Integer> o1, KeyVal<Integer, Integer> o2) {
				int a= o1.getV()-o2.getV();
				if(a==0) {
					a=o1.getK()-o2.getK();
				}
				return a;
			}
		});
		if(cardstype!=CardsType.ZHA_DAN) {
			for(KeyVal<Integer, Integer> find:list) {
				int cardnum=find.getK();
				//找到了
				List<Card> tt=new ArrayList<>();
				tt.addAll(hands);
				return new PdkOut(CardsType.ZHA_DAN, cardnum, select(tt,cardnum,4));
			}
		}else {
			for(KeyVal<Integer, Integer> find:list) {
				int cardnum=find.getK();
				int cardcount=find.getV();
				if(cardnum>max) {
					//找到了
					List<Card> tt=new ArrayList<>();
					tt.addAll(hands);
					return new PdkOut(cardstype, cardnum, select(tt,cardnum,cardcount));
				}
			}
		}
		return null;
	}


	private static PdkOut lookFollowLianDui(List<Card> hands, int cardstype, int max, int length) {
		List<KeyVal<Integer, Integer>> tmp=keyVals(hands);
		List<Integer> cardNums=new ArrayList<>();
		for(KeyVal<Integer, Integer> find:tmp) {
			if(find.getV()>=2&&find.getK()>=3&&find.getK()<=14) {
				cardNums.add(find.getK());
			}
		}
		List<List<Integer>> list=shun(cardNums,length/2);
		Collections.sort(list,new Comparator<List<Integer>>() {

			@Override
			public int compare(List<Integer> o1, List<Integer> o2) {
				return o1.size()-o2.size();
			}
		});
		for(int i=0;i<list.size();i++) {
			List<Integer> find=list.get(i);
			Collections.sort(find);
			int max1=find.get(find.size()-1);
			if(max1>max) {
				//找到了
				return new PdkOut(cardstype, max1, select(hands, find,2));
			}
		}
		return null;
	}

	private static PdkOut lookFollowShun(List<Card> hands, int cardstype, int max, int length) {
		List<KeyVal<Integer, Integer>> tmp=keyVals(hands);
		List<Integer> cardNums=new ArrayList<>();
		for(KeyVal<Integer, Integer> find:tmp) {
			if(find.getV()>=1&&find.getK()>=3&&find.getK()<=14) {
				cardNums.add(find.getK());
			}
		}
		List<List<Integer>> list=shun(cardNums,length);
		Collections.sort(list,new Comparator<List<Integer>>() {

			@Override
			public int compare(List<Integer> o1, List<Integer> o2) {
				return o1.size()-o2.size();
			}
		});
		for(int i=0;i<list.size();i++) {
			List<Integer> find=list.get(i);
			Collections.sort(find);
			int max1=find.get(find.size()-1);
			if(max1>max) {
				//找到了
				return new PdkOut(cardstype, max1, select(hands, find,1));
			}
		}
		return null;
	}
	
	private static List<Card> select(List<Card> tt, List<Integer> cardnums,int count) {
		List<Card> list=new ArrayList<>();
		for(int i=0;i<count;i++) {
			for(Integer cardnum:cardnums) {
				for(Card card:tt) {
					if(card.getCardNum()==cardnum) {
						list.add(card);
						tt.remove(card);
						break;
					}
				}
			}
		}
		return list;
	}

	private static List<List<Integer>> shun(List<Integer> tmp,int size) {
		List<List<Integer>> list = new ArrayList<>();
		List<Integer> unique_cardids=new ArrayList<>();
		for(Integer i:tmp) {
			if(unique_cardids.contains(i)) {
				continue;
			}
			unique_cardids.add(i);
		}
		Collections.sort(unique_cardids);
		for (int i = 0; i < unique_cardids.size(); i++) {
			List<Integer> out = new ArrayList<>();
			Integer card0 = unique_cardids.get(i);
			out.add(card0);
			for (int j = i + 1; j < unique_cardids.size(); j++) {
				Integer card1 = unique_cardids.get(j);
				if (card1 - card0 == j - i) {
					out.add(card1);
					if (out.size() >= size) {
						if (!list.contains(out)) {
							List<Integer> tt = new ArrayList<>();
							tt.addAll(out);
							list.add(tt);
						}
					}
				} else {
					out.clear();
					break;
				}
			}
		}
		return list;
	}
	

	private static PdkOut lookFollowSan(List<Card> hands, int cardstype, int max, int length) {
		List<KeyVal<Integer, Integer>> tmp=keyVals(hands);
		List<KeyVal<Integer,Integer>>list=new ArrayList<>();
		for(KeyVal<Integer, Integer> find:tmp) {
			if(find.getV()>=3) {
				list.add(find);
			}
		}
		Collections.sort(list,new Comparator<KeyVal<Integer,Integer>>() {

			@Override
			public int compare(KeyVal<Integer, Integer> o1, KeyVal<Integer, Integer> o2) {
				int a= o1.getV()-o2.getV();
				if(a==0) {
					a=o1.getK()-o2.getK();
				}
				return a;
			}
		});
		for(KeyVal<Integer, Integer> find:list) {
			int cardnum=find.getK();
			if(cardnum>max) {
				//找到了
				List<Card> tt=new ArrayList<>();
				tt.addAll(hands);
				return new PdkOut(cardstype, cardnum, select(tt,cardnum,3));
			}
		}
		return null;
	}

	private static PdkOut lookFollowDui(List<Card> hands, int cardstype, int max, int length) {
		List<KeyVal<Integer, Integer>> tmp=keyVals(hands);
		List<KeyVal<Integer,Integer>>list=new ArrayList<>();
		for(KeyVal<Integer, Integer> find:tmp) {
			if(find.getV()>=2) {
				list.add(find);
			}
		}
		Collections.sort(list,new Comparator<KeyVal<Integer,Integer>>() {

			@Override
			public int compare(KeyVal<Integer, Integer> o1, KeyVal<Integer, Integer> o2) {
				int a= o1.getV()-o2.getV();
				if(a==0) {
					a=o1.getK()-o2.getK();
				}
				return a;
			}
		});
		for(KeyVal<Integer, Integer> find:list) {
			int cardnum=find.getK();
			if(cardnum>max) {
				//找到了
				List<Card> tt=new ArrayList<>();
				tt.addAll(hands);
				return new PdkOut(cardstype, cardnum, select(tt,cardnum,2));
			}
		}
		return null;
	}

	private static List<Card> select(List<Card> tt, int cardnum, int count) {
		List<Integer> cardnums=new ArrayList<>();
		cardnums.add(cardnum);
		return select(tt, cardnums, count);
	}









	private static PdkOut lookFollowDan(List<Card> hands,int cardstype, int max, int length) {
		List<KeyVal<Integer, Integer>> tmp=keyVals(hands);
		List<KeyVal<Integer,Integer>>list=new ArrayList<>();
		for(KeyVal<Integer, Integer> find:tmp) {
			if(find.getV()>=1) {
				list.add(find);
			}
		}
		Collections.sort(list,new Comparator<KeyVal<Integer,Integer>>() {

			@Override
			public int compare(KeyVal<Integer, Integer> o1, KeyVal<Integer, Integer> o2) {
				int a= o1.getV()-o2.getV();
				if(a==0) {
					a=o1.getK()-o2.getK();
				}
				return a;
			}
		});
		for(KeyVal<Integer, Integer> find:list) {
			int cardnum=find.getK();
			if(cardnum>max) {
				//找到了
				List<Card> tt=new ArrayList<>();
				tt.addAll(hands);
				return new PdkOut(cardstype, cardnum, select(tt,cardnum,1));
			}
		}
		return null;
	}
	

	public static List<Card> selectDechWithHeisan(List<Card> deck, int num) {
		List<Card>  withHeisanDeck=new ArrayList<>();
		Card heisan=lookHeisanFromDeck(deck);
		deck.remove(heisan);
		withHeisanDeck.add(heisan);
		Collections.shuffle(deck);
		withHeisanDeck.addAll(deck.subList(0, num-1));
		Collections.shuffle(withHeisanDeck);
		return withHeisanDeck;
	}

	private static Card lookHeisanFromDeck(List<Card> deck) {
		Card heisan=null;
		for(Card card:deck) {
			if(card.getCardColor()==4&&card.getCardNum()==3) {
				heisan=card;
				break;
			}
		}
		return heisan;
	}

	public static PdkOut parsePdkOut(List<Card> cards, List<Card> hands,PdkConfig pdkConfig, DispatchData pre,LogicController controller) {
		PdkOut pdkOut=null;
		boolean can_zha=checkCanzha(cards,pdkConfig);;
		if(pre==null||pre.getUid()==controller.getId()) {
			//首先打牌
			if(pdkOut==null) {
				pdkOut=isDan(cards);
			}
			if(pdkOut==null) {
				pdkOut=isDui(cards);
			}
			if(pdkOut==null) {
				if(cards.size()==5||(cards.size()<=5&&cards.size()>=3&&cards.size()==hands.size()&&!can_zha)) {
					pdkOut=isSandaier(cards,pdkConfig);
				}
			}
			if(pdkOut==null) {
				pdkOut=isShun(cards);
			}
			if(pdkOut==null) {
				pdkOut=isLiandui(cards);
			}
			if(pdkOut==null) {
				pdkOut=isFeijidaier(cards,hands,pdkConfig);
			}
			if(pdkOut==null&&pdkConfig.getSidaier()==1) {
				if(cards.size()==6||(cards.size()==5&&cards.size()==hands.size())) {
					pdkOut=isSidaier(cards,pdkConfig);
				}
			}
			if(pdkOut==null&&pdkConfig.getSidaisan()==1) {
				if(cards.size()==7||((cards.size()==5||cards.size()==6)&&cards.size()==hands.size())) {
					pdkOut=isSidaisan(cards,pdkConfig);
				}
			}
			if(pdkOut==null) {
				pdkOut=isZhadan(cards,pdkConfig);
			}
		}else {
			//跟牌操作
			if(pdkOut==null&&pre.getPdkOut().getCardstype()==CardsType.DAN) {
				pdkOut=isDan(cards);
			}
			if(pdkOut==null&&pre.getPdkOut().getCardstype()==CardsType.DUI) {
				pdkOut=isDui(cards);
			}
			if(pdkOut==null&&pre.getPdkOut().getCardstype()==CardsType.SAN_DAI_ER) {
				if(cards.size()==5||(cards.size()<=5&&cards.size()>=3&&cards.size()==hands.size()&&!can_zha)) {
					pdkOut=isSandaier(cards,pdkConfig);
				}
			}
			if(pdkOut==null&&pre.getPdkOut().getCardstype()==CardsType.SHUN) {
				pdkOut=isShun(cards);
			}
			if(pdkOut==null&&pre.getPdkOut().getCardstype()==CardsType.LIAN_DUI) {
				pdkOut=isLiandui(cards);
			}
			if(pdkOut==null&&pre.getPdkOut().getCardstype()==CardsType.FEI_JI&&cards.size()<=pre.getPdkOut().getOuts().size()) {
				pdkOut=isFeijidaier(cards,hands,pdkConfig);
			}
			if(pdkOut==null&&pdkConfig.getSidaier()==1&&pre.getPdkOut().getCardstype()==CardsType.SI_DAI_ER) {
				if(cards.size()==6||(cards.size()==5&&cards.size()==hands.size())) {
					pdkOut=isSidaier(cards,pdkConfig);
				}
				if(pdkOut==null&&cards.size()==5&&pdkConfig.getSanazhadan()==1) {
					//三a炸弹
					pdkOut=isSidaier(cards,pdkConfig);
				}
			}
			if(pdkOut==null&&pdkConfig.getSidaisan()==1&&pre.getPdkOut().getCardstype()==CardsType.SI_DAI_SAN) {
				if(cards.size()==7||((cards.size()==5||cards.size()==6)&&cards.size()==hands.size())) {
					pdkOut=isSidaisan(cards,pdkConfig);
				}
				if(pdkOut==null&&cards.size()==6&&pdkConfig.getSanazhadan()==1) {
					//三a炸弹
					pdkOut=isSidaisan(cards,pdkConfig);
				}
			}
			if(pdkOut==null) {
				pdkOut=isZhadan(cards,pdkConfig);
			}
		}
		return pdkOut;
	}

	private static boolean checkCanzha(List<Card> cards,PdkConfig pdkConfig) {
		if(cards.size()==4&&cards.get(0).getCardNum()==cards.get(1).getCardNum()&&cards.get(0).getCardNum()==cards.get(2).getCardNum()&&cards.get(0).getCardNum()==cards.get(3).getCardNum()) {
			return true;
		}
		if(cards.size()==3&&cards.get(0).getCardNum()==cards.get(1).getCardNum()&&cards.get(0).getCardNum()==cards.get(2).getCardNum()&&pdkConfig.getSanazhadan()==1&&cards.get(0).getCardNum()==14) {
			return true;
		}
		return false;
	}

	private static PdkOut isZhadan(List<Card> cards, PdkConfig pdkConfig) {
		Map<Integer,Integer>nummap=numMap(cards);
		if(nummap.size()==1&&nummap.containsValue(4)) {
			return new PdkOut(CardsType.ZHA_DAN, cards.get(0).getCardNum(), cards);
		}
		if(pdkConfig.getSanazhadan()==1) {
			if(nummap.size()==1&&nummap.containsValue(3)&&nummap.containsKey(14)) {
				return new PdkOut(CardsType.ZHA_DAN, cards.get(0).getCardNum(), cards);
			}
		}
		return null;
	}

	private static PdkOut isSidaisan(List<Card> cards,PdkConfig pdkConfig) {
		List<KeyVal<Integer, Integer>> list=keyVals(cards);
		Collections.sort(list,new Comparator<KeyVal<Integer, Integer>>() {
			
			@Override
			public int compare(KeyVal<Integer, Integer> o1, KeyVal<Integer, Integer> o2) {
				int result= o2.getV()-o1.getV();
				if(result==0) {
					result=o2.getK()-o1.getK();
				}
				return result;
			}
		});
		if(list.get(0).getV()==4) {
			int max=list.get(0).getK();
			return new PdkOut(CardsType.SI_DAI_SAN, max, cards);
		}else if(list.get(0).getV()==3&&list.get(0).getK()==14&&pdkConfig.getSanazhadan()==1) {
			//3a炸弹
			int max=list.get(0).getK();
			return new PdkOut(CardsType.SI_DAI_SAN, max, cards);
		}
		return null;
	}

	private static PdkOut isSidaier(List<Card> cards,PdkConfig pdkConfig) {
		if(cards.size()>=5&&cards.size()<=6) {
			List<KeyVal<Integer, Integer>> list=keyVals(cards);
			Collections.sort(list,new Comparator<KeyVal<Integer, Integer>>() {
				
				@Override
				public int compare(KeyVal<Integer, Integer> o1, KeyVal<Integer, Integer> o2) {
					return o2.getV()-o1.getV();
				}
			});
			if(list.get(0).getV()==4) {
				int max=list.get(0).getK();
				return new PdkOut(CardsType.SI_DAI_ER, max, cards);
			}else if(list.get(0).getV()==3&&list.get(0).getK()==14&&pdkConfig.getSanazhadan()==1) {
				//3a炸弹
				int max=list.get(0).getK();
				return new PdkOut(CardsType.SI_DAI_ER, max, cards);
			}
		}
		return null;
	}


	private static PdkOut isFeijidaier(List<Card> cards, List<Card> hands, PdkConfig pdkConfig) {
		if(cards.size()>=6&&cards.size()<=16) {
			List<KeyVal<Integer, Integer>> tmp=keyVals(cards);
			//除去非3张的
			List<KeyVal<Integer,Integer>>list=new ArrayList<>();
			for(KeyVal<Integer, Integer> find:tmp) {
				if(find.getK()>=3&&find.getK()<=14) {
					if(pdkConfig.getZhadankechai()==1) {
						if(find.getV()>=3) {
							list.add(find);
						}
					}else {
						if(find.getV()==3) {
							list.add(find);
						}
					}
				}
			}
			if(list.size()>=2) {
				//找所有可能的顺子
				List<Integer> nums=new ArrayList<>();
				for(KeyVal<Integer,Integer> kv:list) {
					nums.add(kv.getK());
				}
				boolean find=false;
				int max=0;
				List<List<Integer>> allShunzi=getAllShunzi(nums);
				//检查这些顺子哪些合法
				for(List<Integer> shunzi:allShunzi) {
					int size=shunzi.size();
					int min_count=size*3;
					int max_count=size*5;
					if(hands.size()>cards.size()) {
						//手牌数量超过了打牌数量只能5张
						if(cards.size()==max_count) {
							Collections.sort(shunzi,new Comparator<Integer>() {
								
								@Override
								public int compare(Integer o1, Integer o2) {
									return o2-o1;
								}
							});
							max=shunzi.get(0);
							find=true;
							break;
						}
					}else {
						if(cards.size()>=min_count&&cards.size()<=max_count) {
							Collections.sort(shunzi,new Comparator<Integer>() {
								
								@Override
								public int compare(Integer o1, Integer o2) {
									return o2-o1;
								}
							});
							max=shunzi.get(0);
							find=true;
							break;
						}
					}
				}
				
				
				if(find) {
					return new PdkOut(CardsType.FEI_JI, max, cards);
				}
			}
		}
		return null;
	}


	private static PdkOut isLiandui( List<Card> cards) {
		if(cards.size()%2==0&&cards.size()>=4) {
			List<KeyVal<Integer, Integer>> tmp=keyVals(cards);
			//除去非3张的
			List<KeyVal<Integer,Integer>>list=new ArrayList<>();
			for(KeyVal<Integer, Integer> find:tmp) {
				if(find.getV()==2&&find.getK()>=3&&find.getK()<=14) {
					list.add(find);
				}
			}
			
			if(list.size()==cards.size()/2) {
				Collections.sort(list,new Comparator<KeyVal<Integer, Integer>>() {
					
					@Override
					public int compare(KeyVal<Integer, Integer> o1, KeyVal<Integer, Integer> o2) {
						return o2.getK()-o1.getK();
					}
				});
				
				if(list.get(0).getK()-list.get(list.size()-1).getK()+1==list.size()) {
					int max=list.get(0).getK();
					return new PdkOut(CardsType.LIAN_DUI, max, cards);
				}
			}
		}
		return null;
	}

	private static PdkOut isShun( List<Card> cards) {
		if(cards.size()>=5) {
			List<KeyVal<Integer, Integer>> tmp=keyVals(cards);
			List<KeyVal<Integer,Integer>>list=new ArrayList<>();
			for(KeyVal<Integer, Integer> find:tmp) {
				if(find.getV()==1&&find.getK()>=3&&find.getK()<=14) {
					list.add(find);
				}
			}
			
			if(list.size()==cards.size()) {
				Collections.sort(list,new Comparator<KeyVal<Integer, Integer>>() {
					
					@Override
					public int compare(KeyVal<Integer, Integer> o1, KeyVal<Integer, Integer> o2) {
						return o2.getK()-o1.getK();
					}
				});
				
				if(list.get(0).getK()-list.get(list.size()-1).getK()+1==list.size()) {
					int max=list.get(0).getK();
					return new PdkOut(CardsType.SHUN, max, cards);
				}
			}
		}
		return null;
	}

	private static PdkOut isSandaier( List<Card> cards, PdkConfig pdkConfig) {
		if(cards.size()>=3&&cards.size()<=5) {
			List<KeyVal<Integer, Integer>> tmp=keyVals(cards);
			//除去非3张的
			List<KeyVal<Integer,Integer>>list=new ArrayList<>();
			for(KeyVal<Integer, Integer> find:tmp) {
				if(pdkConfig.getZhadankechai()==1) {
					if(find.getV()>=3) {
						list.add(find);
					}
				}else {
					if(find.getV()==3) {
						list.add(find);
					}
				}
			}
			
			if(list.size()==cards.size()/3) {
				int max=list.get(0).getK();
				return new PdkOut(CardsType.SAN_DAI_ER, max, cards);
			}
		}
		return null;
	}


	private static PdkOut isDui( List<Card> cards) {
		if(cards.size()==2&&cards.get(0).getCardNum()==cards.get(1).getCardNum()) {
			return new PdkOut(CardsType.DUI, cards.get(0).getCardNum(), cards);
		}
		return null;
	}

	private static PdkOut isDan(List<Card> cards) {
		if(cards.size()==1) {
			return new PdkOut(CardsType.DAN, cards.get(0).getCardNum(), cards);
		}
		return null;
	}
	
	public static boolean checkAllHas(List<Card> list, List<Integer> cardIds) {
		boolean all=false;
		List<Integer> tmp=new ArrayList<>();
		for(Card card:list) {
			tmp.add(card.getCardId());
		}
		all=tmp.containsAll(cardIds);
		return all;
	}

	public static List<Card> findCardsByCardId(List<Card> list, List<Integer> cardIds) {
		List<Card> cards=new ArrayList<>();
		for(Integer cardId:cardIds) {
			cards.add(findCard(list,cardId));
		}
		return cards;
	}

	private static Card findCard(List<Card> list, Integer cardId) {
		for(Card card:list) {
			if(card.getCardId()==cardId) {
				return card;
			}
		}
		return null;
	}

	

	
	public static List<List<Integer>> getAllShunzi(List<Integer> uniques){
		List<List<Integer>> list=new ArrayList<>();
		for (int i = 0; i < uniques.size(); i++) {
			List<Integer> out = new ArrayList<>();
			int card0 = uniques.get(i);
			out.add(card0);
			for (int j = i + 1; j < uniques.size(); j++) {
				int card1 = uniques.get(j);
				if (card1 - card0 == j - i) {
					out.add(card1);
					if (out.size() >= 2) {
						if (!list.contains(out)) {
							List<Integer> tt = new ArrayList<>();
							tt.addAll(out);
							list.add(tt);
						}
					}
				} else {
					out.clear();
					break;
				}
			}
		}
		return list;
	}
	
	public static void main(String[] args) {
		List<Integer> uniques =new ArrayList<>();
		uniques.add(1);
		uniques.add(2);
		uniques.add(4);
		uniques.add(5);
		uniques.add(6);
		uniques.add(8);
		uniques.add(9);
		System.out.println(getAllShunzi(uniques));
	}
	
}
